using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Transactions;
using context;
using entities;

namespace DataAccessLibrary.DAL
{
    public class EmployeeDAO
    {
        private BlueMDataContext _ctx;

        public EmployeeDAO()
        {
            _ctx = new BlueMDataContext();
        }

        public bool CheckEmployeeAccount(string account)
        {
            IQueryable<Employee> query = _ctx.Employees.Where(p => p.EmployeeAccount == account);
            return query.FirstOrDefault() == null;
        }

        public bool CheckEmployeeEmail(string email)
        {
            IQueryable<Employee> query = from p in _ctx.Employees
                                         where p.EmployeeEmail == email
                                         select p;
            return query.FirstOrDefault() == null;
        }


        private bool validData(string position, string phone, string newemail, string oldemail, string jobtitle,
                               out string err)
        {
            const string lstJobTitle = "Junior Senior";
            var rePhone = new Regex(@"0+\d{2,3}-\d{3}-\d{4}");
            if (!rePhone.IsMatch(phone))
            {
                err = "Phone number mus be valid format. \n" + "0xx[x]-xxx-xxxx";
                return false;
            }

            if (jobtitle == null || lstJobTitle.IndexOf(jobtitle) == -1)
            {
                err = "Grade must be Junior, Senior";
                return false;
            }

            const string lstPosition = "Cleaner Sales Reception Manager";

            if (position == null || lstPosition.IndexOf(position) == -1)
            {
                err = "Job title must be Cleaner, Sales, Reception, Manager";
                return false;
            }

            if (newemail != oldemail)
            {
                int idxA = newemail.IndexOf("@", StringComparison.Ordinal);
                if (idxA == -1)
                {
                    err = "e-mail address must be valid e-mail address format.\nFor example 'someone@example.com' ";
                    return false;
                }
                if (newemail.IndexOf(".", idxA, StringComparison.Ordinal) > idxA)
                {
                    if (CheckEmployeeEmail(newemail))
                    {
                        err = "";
                        return true;
                    }
                    err = "Email address is exits";
                    return false;
                }
            }
            err = "";
            return true;
        }

        public List<vEmployeeSubDetail> SelectEmployee(bool all)
        {
            IQueryable<vEmployeeSubDetail> query = _ctx.vEmployeeSubDetails;
            if (!all)
            {
                query = query.Where(p => p.EmployeeAvailable);
            }
            return query.ToList();
        }

        public Employee SelectEmployeeByID(int employeeID)
        {
            IQueryable<Employee> query = _ctx.Employees;
            query = query.Where(p => p.EmployeeID == employeeID);
            return query.FirstOrDefault();
        }

        public bool InsertEmployee(Employee employee)
        {
            try
            {
                using (var ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 0, 30)))
                {
                    string err;
                    string acc = employee.EmployeeAccount;
                    int pfx = 1;
                    if (!CheckEmployeeAccount(acc))
                    {
                        while (!CheckEmployeeAccount(acc + pfx))
                        {
                            pfx++;
                        }
                        acc = acc + pfx;
                    }
                    employee.EmployeeAccount = acc;


                    if (!validData(employee.EmployeePosition, employee.EmployeePhone, employee.EmployeeEmail, "",
                                   employee.EmployeeJobTitle, out err))
                    {
                        throw new Exception(err);
                    }
                    _ctx.Employees.InsertOnSubmit(employee);
                    _ctx.SubmitChanges();
                    ts.Complete();
                    return true;
                }
            }
            catch
                (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }


        public bool UpdateEmployee(Employee employee)
        {
            try
            {
                using (var ts = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(0, 0, 30)))
                {
                    string err;
                    Employee employeeOld = SelectEmployeeByID(employee.EmployeeID);
                    if (validData(employee.EmployeePosition, employee.EmployeePhone, employee.EmployeeEmail,
                                  employeeOld.EmployeeEmail, employee.EmployeeJobTitle, out err))
                    {
                        employeeOld.EmployeeName = employee.EmployeeName;
                        employeeOld.EmployeeSex = employee.EmployeeSex;
                        employeeOld.EmployeeBirthday = employee.EmployeeBirthday;
                        employeeOld.EmployeePosition = employee.EmployeePosition;
                        employeeOld.EmployeePhone = employee.EmployeePhone;
                        employeeOld.EmployeeEmail = employee.EmployeeEmail;
                        employeeOld.EmployeeAddress = employee.EmployeeAddress;
                        employeeOld.EmployeeCity = employee.EmployeeCity;
                        employeeOld.EmployeeCountry = employee.EmployeeCountry;
                        employeeOld.EmployeeJobTitle = employee.EmployeeJobTitle;
                        employeeOld.EmployeeImage = employee.EmployeeImage;
                        employeeOld.EmployeeAvailable = employee.EmployeeAvailable;

                        _ctx.SubmitChanges();
                        ts.Complete();
                        return true;
                    }
                    throw new Exception(err);
                }
            }
            catch (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }

        public bool DeactiveEmployee(int employeeID)
        {
            try
            {
                Employee employee = SelectEmployeeByID(employeeID);
                employee.EmployeeAvailable = false;
                employee.EmployeePassword = "";
                employee.EmployeeEmail = "";
                _ctx.SubmitChanges();
                return true;
            }
            catch (Exception)
            {
                _ctx = new BlueMDataContext();
                throw;
            }
        }

        public List<vEmployeeSubDetail> SearchEmployeeByName(string searVal)
        {
            IQueryable<vEmployeeSubDetail> query = _ctx.vEmployeeSubDetails;
            query = query.Where(e => e.EmployeeName.Contains(searVal));
            return query.ToList();
        }
    }
}